package com.topisv.tms.service.stock.check;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.hibernate.ejb.criteria.predicate.ComparisonPredicate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.entity.AreaGroup;
import com.topisv.tms.entity.Customers;
import com.topisv.tms.entity.User;
import com.topisv.tms.entity.stock.check.CheckFixTask;
import com.topisv.tms.entity.stock.check.CheckPlan;
import com.topisv.tms.entity.stock.check.CheckPlanItem;
import com.topisv.tms.entity.stock.reverse.ReverseBill;
import com.topisv.tms.entity.stock.reverse.ReverseBillItem;
import com.topisv.tms.repository.AreaGroupDao;
import com.topisv.tms.repository.CustomersDao;
import com.topisv.tms.repository.UserDao;
import com.topisv.tms.repository.stock.check.CheckFixTaskDao;
import com.topisv.tms.repository.stock.check.CheckPlanDao;
import com.topisv.tms.repository.stock.check.CheckPlanItemDao;
import com.topisv.tms.repository.stock.reverse.ReverseBillDao;
import com.topisv.tms.repository.stock.reverse.ReverseBillItemDao;
import com.topisv.tms.service.account.ShiroDbRealm.ShiroUser;
import com.topisv.tms.utils.rule.TMSTransportRule;

@Component
@Transactional(readOnly = true)
public class CheckFixTaskService {
	
	@Autowired
	private CheckFixTaskDao checkFixTaskDao;
	@Autowired
	private CustomersDao customersDao;
	@Autowired
	private AreaGroupDao areaGroupDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private CheckPlanDao checkPlanDao;
	@Autowired
	private CheckPlanItemDao checkPlanItemDao;
	@Autowired
	private ReverseBillDao reverseBillDao;
	@Autowired
	private ReverseBillItemDao reverseBillItemDao;

	/**
	 * 查询任务
	 * @param params
	 * @return
	 */
	public List<CheckFixTask> loadTask(Map<String, Object> params) {
		Sort sort = new Sort(Sort.Direction.DESC,"id");
	    Specification<CheckFixTask> spec =this.getWhereClause(params);
	    List<CheckFixTask> taskList = this.checkFixTaskDao.findAll(spec, sort);
	    for (CheckFixTask task : taskList) {
			this.setDetail(task);
		}
	    return taskList;
	}
	
	
	/**
	 * 设置属性
	 * @param task
	 */
	private void setDetail(CheckFixTask task){
		//customer
		String customerCode=task.getCustomerCode();
		Customers customer=this.customersDao.findByCustomerCode(customerCode);
		task.setCustomer(customer);
		
		//warehouse
		String warehouseCode=task.getWarehouseCode();
		AreaGroup warehouse=this.areaGroupDao.findByGroupCode(warehouseCode);
		task.setWarehouse(warehouse);
		
		//creater
		User user=this.userDao.findByJobuuid(task.getWorkerUuid());
		task.setWorker(user);
		
		//checkPlan
		CheckPlan plan=this.checkPlanDao.loadByPlanCode(task.getPlanCode());
		task.setPlan(plan);
	}
	
	/**
	 * 条件封装
	 * @param params
	 * @return
	 */
	private Specification<CheckFixTask> getWhereClause(final Map<String, Object> params) {
		 return new Specification<CheckFixTask>(){
		    @Override
		    public Predicate toPredicate(Root<CheckFixTask> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
		      Predicate pre = cb.conjunction();
		      
		      //customerCodes
		      String customerCodes=(String) params.get("customerCodes");
		      if(StringUtils.isNotBlank(customerCodes)){
		    	  String[] customerCodeSplit = customerCodes.split(":");
				  ComparisonPredicate[] tempCustomerCode = new ComparisonPredicate[customerCodeSplit.length];
				  int i = 0;
				  for (String _customerCode : customerCodeSplit) {
					 tempCustomerCode[i] = (ComparisonPredicate) cb.equal(r.get("customerCode"), _customerCode);
					 i++;
				  }
				  pre.getExpressions().add(cb.or(tempCustomerCode));
		      }
			  
		      
		      //areagroups
		      String areagroups=(String) params.get("areagroups");
		      if(StringUtils.isNotBlank(areagroups)){
		    	  String[] areagroupSplit = areagroups.split(":");
				  ComparisonPredicate[] areagroupArray = new ComparisonPredicate[areagroupSplit.length];
				  int j = 0;
				  for (String _areagroup : areagroupSplit) {
						areagroupArray[j] = (ComparisonPredicate) cb.equal(r.get("warehouseCode"), _areagroup);
						j++;
				  }
				  pre.getExpressions().add(cb.or(areagroupArray)); 
		      }
			  
			  
              //createTime
		      Date fromDate= (Date) params.get("fromDate");
		      if (fromDate != null) {
		        pre.getExpressions().add(cb.greaterThanOrEqualTo(r.<Date>get("createTime"), fromDate));
		      }
		      Date toDate= (Date) params.get("toDate");
		      if (toDate != null) {
		        pre.getExpressions().add(cb.lessThanOrEqualTo(r.<Date>get("createTime"), toDate));
		      }
		      
		      //status
		      String status=(String) params.get("status");
		      if(StringUtils.isNotBlank(status)){
		    	  if("myTask".equals(status)){
		    		  pre.getExpressions().add(cb.or(
		    				  cb.equal(r.get("status"),"token"),
		    				  cb.equal(r.get("status"),"doing")
		    		  )); 
		    	  }else{
		    		  pre.getExpressions().add(cb.equal(r.get("status"),status));
		    	  }
			  }
		      
		      //workerUuid
		      String workerUuid=(String) params.get("workerUuid");
		      if(StringUtils.isNotBlank(workerUuid)){
					pre.getExpressions().add(cb.equal(r.get("workerUuid"),workerUuid));
			  }
		      
		      return pre;
		    }
		  };
	}


	/**
	 * 领取校对任务
	 * @param taskId
	 * @param jobuuid
	 */
	@Transactional(readOnly = false)
	public String takeTask(Long taskId, String jobuuid) {
		
		CheckFixTask task=this.checkFixTaskDao.findOne(taskId);
		
		//已经被领取
		if(!"undo".equals(task.getStatus())){
			return "token"; 
		}
		
		//领取
		task.setStatus("token");
		task.setWorkerUuid(jobuuid);
		this.checkFixTaskDao.save(task);
		
		//修改计划状态：领取校对任务
		CheckPlan plan=this.checkPlanDao.loadByPlanCode(task.getPlanCode());
		plan.setStatus("4"); //状态 （1.创建盘点计划 2.领取点数任务 3.点数任务完成 4.领取校对任务 5.校对任务完成）
		this.checkPlanDao.save(plan);
		
		return "success";
	}
	
	/**
	 * 查询
	 * @param taskId 任务ID
	 * @return
	 */
	public CheckFixTask loadById(Long taskId) {
		return this.checkFixTaskDao.findOne(taskId);
	}
	

	/**
	 * 完成校对
	 * @param jsonArray
	 * @throws Exception 
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void finishFixData(String countTaskCode) throws Exception {
		try {
			
			//修改校对任务状态：完成
			CheckFixTask fixTask=this.checkFixTaskDao.loadByTaskCode(countTaskCode);
			fixTask.setStatus("finish");
			this.checkFixTaskDao.save(fixTask);
			
			//修改计划状态：完成校对
			CheckPlan plan=this.checkPlanDao.loadByPlanCode(fixTask.getPlanCode());
			plan.setStatus("5"); //状态 （1.创建盘点计划 2.领取点数任务 3.点数任务完成 4.领取校对任务   5.校对任务完成）
			this.checkPlanDao.save(plan);
			
			//创建冲正数据
			List<CheckPlanItem> itemList=this.checkPlanItemDao.loadByCondition(plan.getPlanCode(),"reverse"); //查询需要冲正的数据
			if(itemList.size()>0){
				
				Date now=new Date();
				ShiroUser curUser = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
				
				//冲正单
				ReverseBill bill=new ReverseBill();
				bill.setAboutCode(plan.getPlanCode());
				bill.setBillCode(TMSTransportRule.generateReverseBillCode());
				bill.setBillType("check");
				bill.setCreaterUuid(curUser.jobuuid);
				bill.setCreateTime(now);
				bill.setCustomerCode(plan.getCustomerCode());
				bill.setWarehouseCode(plan.getWarehouseCode());
				bill.setStatus("undo");
				bill.setIsAllocated("Y");
				this.reverseBillDao.save(bill);
				
				//冲正明细
				List<ReverseBillItem> billItemList=new ArrayList<ReverseBillItem>();
				for (CheckPlanItem checkItem : itemList) {
					String reverseFlag=checkItem.getReverseFlag();
					if(!"reverse".equals(reverseFlag)){
						continue;
					}
					ReverseBillItem billItem=new ReverseBillItem();
					billItem.setBillCode(bill.getBillCode());
					billItem.setBoxCode(checkItem.getBoxCode());
					billItem.setCustomerCode(billItem.getCustomerCode());
					billItem.setOrderNumFix(checkItem.getOrderNumFix());
					billItem.setSalesNumFix(checkItem.getSalesNumFix());
					billItem.setSku(checkItem.getSku());
					billItem.setBatchCode(checkItem.getBatchCode());
					billItem.setProductDate(checkItem.getProductDate());
					billItem.setExpireDate(checkItem.getExpireDate());
					billItem.setStatus("undo");
					billItem.setStockCode(checkItem.getStockCode());
					billItem.setUnusedNumFix(checkItem.getUnusedNumFix());
					billItem.setWarehouseCode(checkItem.getWarehouseCode());
					billItem.setCustomerCode(checkItem.getCustomerCode());
					
					billItemList.add(billItem);
				}
				this.reverseBillItemDao.save(billItemList);
				
			}
			
			
		} catch (Exception e) {
			throw e;
		}
	}

	

	/**
	 * 标识冲正
	 * @param itemId
	 */
	@Transactional(readOnly = false)
	public void reverse(Long itemId,String reverseFlag) {
		try {
			CheckPlanItem item=this.checkPlanItemDao.findOne(itemId);
			item.setReverseFlag(reverseFlag);
			this.checkPlanItemDao.save(item);
		} catch (Exception e) {
			
		}
		
	}
	

}